# Author: Kwasi Mensah (kmensah@andrew.cmu.edu)
# Date: 8/02/2005
# Modified by: me (as118410@gmail.com)
#
# This is meant to be a simple example of how to draw a cube
# using Panda's new Geom Interface. Quads arent directly supported 
# since they get broken down to trianlges anyway.
#

from direct.directbase import DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.gui.DirectGui import *
from direct.interval.IntervalGlobal import *
from panda3d.core import lookAt
from panda3d.core import GeomVertexFormat, GeomVertexData
from panda3d.core import Geom, GeomTriangles, GeomVertexWriter
from panda3d.core import Texture, GeomNode
from panda3d.core import PerspectiveLens
from panda3d.core import CardMaker
from panda3d.core import Light, Spotlight
from panda3d.core import TextNode
from panda3d.core import Vec3, Vec4, Point3

base.disableMouse()
base.camera.setPos(0, 0, -10)

title = OnscreenText(text="Panda3D: Tutorial - Creating sample terrain procedurally",
                       style=1, fg=(1,1,1,1),
                       pos=(0.25,-0.95), scale = .07)
escapeEvent = OnscreenText( 
              text="1: Set a Texture onto the Cube",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.95),
             align=TextNode.ALeft, scale = .05)
spaceEvent = OnscreenText( 
              text="2: Toggle Light from the front On/Off",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.90),
             align=TextNode.ALeft, scale = .05)
upDownEvent = OnscreenText( 
              text="3: Toggle Light from on top On/Off",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.85),
             align=TextNode.ALeft, scale = .05)


cameraLeft = OnscreenText( 
              text="A: Move camera to the left",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.80),
             align=TextNode.ALeft, scale = .05)
cameraRight = OnscreenText( 
              text="D: Move camera to the right",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.75),
             align=TextNode.ALeft, scale = .05)
cameraForward = OnscreenText( 
              text="W: Move camera forward",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.70),
             align=TextNode.ALeft, scale = .05)
cameraBack = OnscreenText( 
              text="A: Move camera backwards",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.65),
             align=TextNode.ALeft, scale = .05)
cameraUp = OnscreenText( 
              text="Z: Move camera up",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.60),
             align=TextNode.ALeft, scale = .05)
cameraDown = OnscreenText( 
              text="X: Move camera down",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.55),
             align=TextNode.ALeft, scale = .05)

## j, k, l, i
cameraRotateLeft = OnscreenText( 
              text="J: Rotate camera towards left",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.50),
             align=TextNode.ALeft, scale = .05)

cameraRotateRight = OnscreenText( 
              text="L: Rotate camera towards right",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.45),
             align=TextNode.ALeft, scale = .05)

cameraRotateUp = OnscreenText( 
              text="I: Rotate camera up",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.40),
             align=TextNode.ALeft, scale = .05)

cameraRotateDown = OnscreenText( 
              text="K: Rotate camera down",
                  style=1, fg=(1,1,1,1), pos=(-1.3, 0.35),
             align=TextNode.ALeft, scale = .05)


#you cant normalize in-place so this is a helper function
# normalizacja wektora: podzielenie go przez samego siebie tak,
# by powstal wektor jednostkowy

def myNormalize(myVec):
    myVec.normalize()
    return myVec


#helper function to make a polygon while given all of its four corners 
def makePolygon(x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4):
    format=GeomVertexFormat.getV3n3cpt2()
    vdata=GeomVertexData('polygon', format, Geom.UHDynamic)
    
    vertex=GeomVertexWriter(vdata, 'vertex')
    normal=GeomVertexWriter(vdata, 'normal')
    color=GeomVertexWriter(vdata, 'color')
    texcoord=GeomVertexWriter(vdata, 'texcoord')
    
    #make sure we draw the sqaure in the right plane
    # yeah right... let's just assume everything;s according to my plan
    vertex.addData3f(x1, y1, z1)
    vertex.addData3f(x2, y2, z2)
    vertex.addData3f(x3, y3, z3)
    vertex.addData3f(x4, y4, z4)

    normal.addData3f(myNormalize(Vec3(2*x1-1, 2*y1-1, 2*z2-1)))
    normal.addData3f(myNormalize(Vec3(2*x2-1, 2*y2-1, 2*z1-1)))
    normal.addData3f(myNormalize(Vec3(2*x3-1, 2*y3-1, 2*z3-1)))
    normal.addData3f(myNormalize(Vec3(2*x4-1, 2*y4-1, 2*z4-1)))
        


    #adding different colors to the vertex for visibility
    color.addData4f(1.0,0.0,0.0,1.0)
    color.addData4f(0.0,1.0,0.0,1.0)
    color.addData4f(0.0,0.0,1.0,1.0)
    color.addData4f(1.0,0.0,1.0,1.0)

    texcoord.addData2f(0.0, 1.0)
    texcoord.addData2f(0.0, 0.0)
    texcoord.addData2f(1.0, 0.0)
    texcoord.addData2f(1.0, 1.0)

    #quads arent directly supported by the Geom interface
    #you might be interested in the CardMaker class if you are
    #interested in rectangle though
    tri1=GeomTriangles(Geom.UHDynamic)
    tri2=GeomTriangles(Geom.UHDynamic)

    tri1.addVertex(0)
    tri1.addVertex(1)
    tri1.addVertex(3)

    tri2.addConsecutiveVertices(1,3)

    tri1.closePrimitive()
    tri2.closePrimitive()


    square=Geom(vdata)
    square.addPrimitive(tri1)
    square.addPrimitive(tri2)
    
    return square




# wspolrzedne musza byc podawane po kolei, np. zgodnie z ruchem wskazowek zegara
#square5 = makePolygon(1, 1, 1,  2, 1, 1,  2, 1, 2,    1, 1, 2)

# zrobmy sobie przykladowa tablice wypelniona liczbami


from heightmap import Heightmap

size = 100
heightmap = Heightmap()

heights = heightmap.createNewHeightmap(size)

#import matplotlib.pyplot as plt
##
#plt.imshow(heights)
#plt.show()

# tablica na trzymanie wszystkich polygonow
polygons = []

yNext = 0
yNext = 0

# chodzimy po tablicy wyskosci i tworzymy nowe polygony

        

for x in xrange(size - 1):
    for y in xrange(size - 1):
        xNext = (x+1)%size
        yNext = (y+1)%size
        polygons.append(makePolygon(x, y, heights[x][y],     xNext, y, heights[xNext][y],      xNext, yNext, heights[xNext][yNext],   x, yNext, heights[x][yNext]))
        


base.camera.lookAt(0, 0, 128)


snode=GeomNode('square')

for poly in polygons:
    
    snode.addGeom(poly)

cube=render.attachNewNode(snode)
#cube.hprInterval(30,Point3(360,360,360)).loop()

#OpenGl by default only draws "front faces" (polygons whose vertices are specified CCW).
cube.setTwoSided(True)

class MyTapper(DirectObject):
    def __init__(self):
        self.testTexture=loader.loadTexture("maps/envir-ground.jpg")
        self.accept("1", self.toggleTex)
        self.accept("2", self.toggleLightsSide)
        self.accept("3", self.toggleLightsUp)
        self.accept("a", self.camXPlus)
        self.accept("d", self.camXMinus)
        self.accept("w", self.camUp)
        self.accept("s", self.camDown)
        self.accept("z", self.camForward)
        self.accept("x", self.camBackwards)
        self.accept("i", self.camRotUp)
        self.accept("j", self.camRotLeft)
        self.accept("k", self.camRotDown)
        self.accept("l", self.camRotRight)
        
        self.LightsOn=False
        self.LightsOn1=False
        slight = Spotlight('slight')
        slight.setColor(Vec4(1, 1, 1, 1))
        lens = PerspectiveLens()
        slight.setLens(lens)
        self.slnp = render.attachNewNode(slight)
        self.slnp1= render.attachNewNode(slight)
        
    def toggleTex(self):
        global cube
        if cube.hasTexture():
            cube.setTextureOff(1)
        else:
            cube.setTexture(self.testTexture)
        
    def toggleLightsSide(self):
        global cube
        self.LightsOn=not(self.LightsOn)
        
        if self.LightsOn:
            render.setLight(self.slnp)
            self.slnp.setPos(cube, 10,-400,0)
            self.slnp.lookAt(Point3(10, 0, 0))
        else:
            render.setLightOff(self.slnp)

    def toggleLightsUp(self):
        global cube
        self.LightsOn1=not(self.LightsOn1)
        
        if self.LightsOn1:
            render.setLight(self.slnp1)
            self.slnp1.setPos(cube, 10,0,400)
            self.slnp1.lookAt(Point3(10, 0, 0))
        else:
            render.setLightOff(self.slnp1)
            
    def camXPlus(self):
        x = base.camera.getX()
        y = base.camera.getY()
        z = base.camera.getZ()
        
        base.camera.setPos(x+10, y, z)
        
    def camXMinus(self):
        x = base.camera.getX()
        y = base.camera.getY()
        z = base.camera.getZ()
        
        base.camera.setPos(x-10, y, z)
        
    def camForward(self):
        x = base.camera.getX()
        y = base.camera.getY()
        z = base.camera.getZ()
        
        base.camera.setPos(x, y+10, z)
        
    def camBackwards(self):
        x = base.camera.getX()
        y = base.camera.getY()
        z = base.camera.getZ()
        
        base.camera.setPos(x, y-10, z)
        
    def camUp(self):
        x = base.camera.getX()
        y = base.camera.getY()
        z = base.camera.getZ()
        
        base.camera.setPos(x, y, z+10)
        
    def camDown(self):
        x = base.camera.getX()
        y = base.camera.getY()
        z = base.camera.getZ()
        
        base.camera.setPos(x, y, z-10)
        
    def camRotLeft(self):
        h = base.camera.getH()
        p = base.camera.getP()
        r = base.camera.getR()
        
        base.camera.setHpr(h, p-10, r)
        
    def camRotRight(self):
        h = base.camera.getH()
        p = base.camera.getP()
        r = base.camera.getR()
        
        base.camera.setHpr(h, p+10, r)
        
    def camRotUp(self):
        h = base.camera.getH()
        p = base.camera.getP()
        r = base.camera.getR()
        
        base.camera.setHpr(h+10, p, r)
        
    def camRotDown(self):
        h = base.camera.getH()
        p = base.camera.getP()
        r = base.camera.getR()
        
        base.camera.setHpr(h-10, p, r)
            
            

t=MyTapper()

run()


# zalozenie 1 - mamy podawac dwa wymiary mapy


